/*
  射手类，用于管理射手的移动和射击等操作。
*/
import * as TWEEN from '@tweenjs/tween.js';

export class Shooter {
  panel: any = null;
  arrow: any = null;
  box: any = null;
  pao: any = null;
  events: any = {};
  angle: number = 360;
  tween: any = null;

  constructor() {
    this.panel = document.getElementById("guide-panel");
    this.pao = document.getElementById("shooter-pao");
    this.arrow = document.getElementById("guide-arrow");
    this.box = document.getElementById("game-box");
    this.addSwipeListener();
    requestAnimationFrame(this.animate.bind(this));
  }

  on(event: string, callback: any) {
    // 给事件绑定回调函数
    if (!this.events[event]) {
      this.events[event] = [];
    }
    this.events[event].push(callback);
  }

  emit(event: string, data?: any) {
    const callbacks = this.events[event];
    if (callbacks) {
      callbacks.forEach((callback: (arg: any) => void) => {
        callback(data);
      });
    }
  }
  animate(time: number) {
    requestAnimationFrame(this.animate.bind(this));
    this.tween?.update(time);
  }
  guide(targetAngle: number) {
    // console.log('start', this.angle, 'end', targetAngle);
    // 清除之前的动画
    if (this.tween) {
      this.tween.stop();
    };
    const start = { angle: this.angle };
    const end = { angle: targetAngle };

    this.tween = new TWEEN.Tween(start)
      .to(end, 200) // 动画持续时间 200ms
      .easing(TWEEN.Easing.Quadratic.Out) // 使用缓动函数
      .onUpdate(() => {
        // 每帧更新角度并应用到箭头
        this.arrow.style.transform = `translateX(-50%) rotate(${start.angle}deg)`;
        this.angle = start.angle;
      })
      .start();
  }

  addSwipeListener() {
    const self = this;

    let eventTouchstart, eventTouchmove, eventTouchend;
    let touchEndClientX: number, touchEndClientY: number;
    let isDragging = false; // 拖动状态标志
    let delay: any = null; // 定时器

    if ('PointerEvent' in window) {
      eventTouchstart = "pointerdown";
      eventTouchmove = "pointermove";
      eventTouchend = "pointerup";
    } else {
      eventTouchstart = "touchstart";
      eventTouchmove = "touchmove";
      eventTouchend = "touchend";
    }

    const arrow = this.arrow.getBoundingClientRect();
    const arrawX = arrow.left + this.arrow.offsetWidth / 2;
    const arrawY = arrow.top + this.arrow.offsetHeight / 2;
    const pao = this.pao.getBoundingClientRect();
    const box = this.box.getBoundingClientRect();
    const paoX = pao.left - box.left;
    const paoY = pao.top - box.top;

    const toGuide = (event: any) => {
      if ('PointerEvent' in window) {
        touchEndClientX = event.pageX;
        touchEndClientY = event.pageY;
      } else {
        touchEndClientX = event.changedTouches[0].clientX;
        touchEndClientY = event.changedTouches[0].clientY;
      }

      if (delay) clearTimeout(delay);
      delay = setTimeout(function () {
        // 计算从箭头中心到触摸点的角度,使用 Math.atan2 计算弧度（范围 -π 到 π），度数范围 -180° 到 180°
        let angle = radianTOAngle(Math.atan2(touchEndClientY - arrawY, touchEndClientX - arrawX));
        //上半圆从右到到左 0--180，下半圆0-180
        // console.log(angle);
        if (angle < 0) {
          const angleOffset = 180 - Math.min(170, Math.max(10, Math.abs(angle))) //180- 调整成从左到右
          // 转换为rotate 0°-360°，从正上方360/0 顺时针增加
          self.guide(270 + angleOffset);
        } else {
          if (angle > 90) {
            self.guide(280);
          } else if (angle < 90) {
            self.guide(440);
          }
        }
        self.emit("line", { radian: angleToRadian(90 - normalizeAngle(self.angle)), cl: paoX, ct: paoY },);
      }, 10);
    }

    this.panel?.addEventListener(eventTouchstart, function (event: any) {
      event.preventDefault();
      // isDragging = true; // 开始拖动
      toGuide(event);
    });

    this.panel?.addEventListener(eventTouchmove, function (event: any) {
      event.stopPropagation()
      event.preventDefault()
      // if (!isDragging) return; // 只有在拖动时才处理
      toGuide(event);
    });

    this.panel?.addEventListener(eventTouchend, function (event: any) {
      event.preventDefault();
      isDragging = false; // 停止拖动
      // 基准轴调整：rotate的0°对应数学的90°，需偏移 -90°, 顺时针旋转取负
      self.emit("shoot", { radian: angleToRadian(90 - normalizeAngle(self.angle)), cl: paoX, ct: paoY },);
    });
  }
}

const normalizeAngle = (angle: number) => {
  // 角度可能超出 [0°, 360°)，先归一化：
  return ((angle % 360) + 360) % 360;
}

const radianTOAngle = (radian: number) => {
  return radian * 180 / Math.PI;
}

const angleToRadian = (angle: number) => {
  return angle * Math.PI / 180;
}
